home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / djgpp / contrib / dvx / demos / maze / maze.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-15  |  20.1 KB  |  795 lines

  1. /******************************************************************************
  2.  * [ maze ] ...
  3.  *
  4.  * modified:  [ 10-4-88 ]  Richard Hess    ...!uunet!cimshop!rhess  
  5.  *              [ Revised primary execution loop within main()...
  6.  *              [ Extended X event handler, check_events()...
  7.  * modified:  [ 1-29-88 ]  Dave Lemke      lemke@sun.com  
  8.  *              [ Hacked for X11...
  9.  *              [  Note the word "hacked" -- this is extremely ugly, but at 
  10.  *              [   least it does the job.  NOT a good programming example 
  11.  *              [   for X.
  12.  * original:  [ 6/21/85 ]  Martin Weiss    Sun Microsystems  [ SunView ]
  13.  *
  14.  ******************************************************************************
  15.  Copyright 1988 by Sun Microsystems, Inc. Mountain View, CA.
  16.   
  17.  All Rights Reserved
  18.   
  19.  Permission to use, copy, modify, and distribute this software and its
  20.  documentation for any purpose and without fee is hereby granted, 
  21.  provided that the above copyright notice appear in all copies and that
  22.  both that copyright notice and this permission notice appear in 
  23.  supporting documentation, and that the names of Sun or MIT not be
  24.  used in advertising or publicity pertaining to distribution of the
  25.  software without specific prior written permission. Sun and M.I.T. 
  26.  make no representations about the suitability of this software for 
  27.  any purpose. It is provided "as is" without any express or implied warranty.
  28.  
  29.  SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  30.  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  31.  PURPOSE. IN NO EVENT SHALL SUN BE LIABLE FOR ANY SPECIAL, INDIRECT
  32.  OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  33.  OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
  34.  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  35.  OR PERFORMANCE OF THIS SOFTWARE.
  36.  *****************************************************************************/
  37.  
  38. #if defined (PROTO) || defined(PROTO1) /* JDC 91/04/22 */
  39. #define NeedFunctionPrototypes 0
  40. #define NeedFunctionPtrPrototypes 1
  41. #include "maze.fd1"
  42. #endif
  43.  
  44. #if PROTO
  45. #include "maze.fd2"
  46. #endif
  47.  
  48. #include  <stdio.h>
  49. #include  <X11/Xlib.h>
  50. #include  <X11/Xutil.h>
  51. #include  <X11/Xos.h>
  52. #include  <X11/bitmaps/gray1>
  53. #include  <X11/bitmaps/xlogo64>
  54. #define logo_width xlogo64_width
  55. #define logo_height xlogo64_height
  56. #define logo_bits xlogo64_bits
  57.  
  58. #define LOGOSIZE    7
  59. #define MIN_MAZE_SIZE    3
  60. #ifdef INTIS16BITS /* POHC 90/10/09 */
  61. #define MAX_MAZE_SIZE_X    60
  62. #define MAX_MAZE_SIZE_Y    64
  63. #else /* INTIS16BITS */
  64. #define MAX_MAZE_SIZE_X    205
  65. #define MAX_MAZE_SIZE_Y    205
  66. #endif /* INTIS16BITS */
  67.  
  68. #define MOVE_LIST_SIZE  (MAX_MAZE_SIZE_X * MAX_MAZE_SIZE_Y)
  69.   
  70. #define WALL_TOP    0x8000
  71. #define WALL_RIGHT    0x4000
  72. #define WALL_BOTTOM    0x2000
  73. #define WALL_LEFT    0x1000
  74.   
  75. #define DOOR_IN_TOP    0x800
  76. #define DOOR_IN_RIGHT    0x400
  77. #define DOOR_IN_BOTTOM    0x200
  78. #define DOOR_IN_LEFT    0x100
  79. #define DOOR_IN_ANY    0xF00
  80.   
  81. #define DOOR_OUT_TOP    0x80
  82. #define DOOR_OUT_RIGHT    0x40
  83. #define DOOR_OUT_BOTTOM    0x20
  84. #define DOOR_OUT_LEFT    0x10
  85.   
  86. #define START_SQUARE    0x2
  87. #define END_SQUARE    0x1
  88.   
  89. #define SQ_SIZE_X    10
  90. #define SQ_SIZE_Y       10
  91.   
  92. #define NUM_RANDOM      100
  93.   
  94. #define    BORDERWIDTH     2
  95. #define    border_x        (0)
  96. #define    border_y        (0)
  97. #define    MIN_W            200
  98. #define    MIN_H            200
  99.  
  100. #define    DEF_W            636
  101. #define    DEF_H            456
  102. char *defgeo = "636x456+10+10";
  103.   
  104. #if defined(SYSV) || defined(METAWARE_V3)         /* MEA 92/7/29 */
  105. #define random rand
  106. #define srandom srand
  107. #endif
  108.  
  109. #if !defined(INTIS16BITS) && !defined(__GNUC__) /* POHC 90/10/09 */ 
  110. extern long random();
  111. #endif
  112.  
  113. #define    get_random(x)    (random() % (x))
  114.   
  115. static int logo_x, logo_y;
  116.  
  117. static unsigned short maze[MAX_MAZE_SIZE_X][MAX_MAZE_SIZE_Y];
  118.  
  119. static struct {
  120.   unsigned char x;
  121.   unsigned char y;
  122.   unsigned char dir;
  123. } move_list[MOVE_LIST_SIZE], save_path[MOVE_LIST_SIZE], path[MOVE_LIST_SIZE];
  124.  
  125. static int maze_size_x, maze_size_y;
  126. static int sqnum, cur_sq_x, cur_sq_y, path_length;
  127. static int start_x, start_y, start_dir, end_x, end_y, end_dir;
  128.  
  129. Display    *dpy;
  130. Window    win;
  131. Window    iwin;
  132. GC    gc, cgc;
  133. XWindowAttributes win_attr;
  134. int    screen;
  135. long    background;
  136. Pixmap    logo_map;
  137. int    reverse = 0;
  138.  
  139. int    width = DEF_W, height = DEF_H ;
  140. int    x = 0, y = 0, restart = 0, stop = 1, state = 1;
  141.  
  142.  
  143. main(argc,argv)                                               /* main module */
  144.      int argc;
  145.      char **argv;
  146. {
  147.   extern int    optind;
  148.   extern char    *optarg;
  149.   char    *display = NULL;
  150.   char    *geo = NULL;
  151.   char    *cmd;
  152.   int    c;
  153.   extern char    *getenv();
  154.   int    screen_saver = 0;
  155.   int   pause = 0; /* POHC 90/10/30 */
  156.   XSizeHints size_hints;
  157.   Pixmap gray;
  158.   int bw = 2;
  159.   int flags;
  160.  
  161.   cmd = argv[0];
  162.   while ((c = getopt(argc, argv, "rpSd:g:")) != EOF)
  163.     switch(c)    {
  164.       
  165.     case 'S':
  166.       screen_saver = 1;
  167.       break;
  168.     case 'd':
  169.       display = optarg;
  170.       break;
  171.     case 'p': /* POHC 90/10/30 */
  172.       pause = 1;
  173.       break;
  174.     case 'g':
  175.       geo = optarg;
  176.       break;
  177.     case 'r':
  178.       reverse = 1;
  179.       break;
  180.     case '?':
  181.       usage(cmd);
  182.       exit(0);
  183.     }
  184.   
  185.   if ((dpy = XOpenDisplay(display)) == NULL)    {
  186.     fprintf(stderr, "Can\'t open display: %s\n",
  187.         (display ? display : getenv("DISPLAY")));
  188.     exit(0);
  189.   }
  190.   screen = DefaultScreen(dpy);
  191.   
  192.   if (screen_saver)    {
  193.     width = DisplayWidth(dpy, screen) - 2 * BORDERWIDTH;
  194.     height = DisplayHeight(dpy, screen) - 2 * BORDERWIDTH;
  195.     x = 0; y = 0;
  196.     flags = (USPosition | USSize);
  197.   } else {
  198.     flags = XGeometry (dpy, DefaultScreen(dpy), geo, defgeo, bw, 1, 1, 0, 0,
  199.                &x, &y, &width, &height);
  200.   }
  201.  
  202.  
  203.   if (reverse)
  204.     background = BlackPixel(dpy, screen) ;
  205.   else
  206.     background = WhitePixel(dpy, screen) ;
  207.  
  208.   win = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), x, y, width,
  209.                 height, BORDERWIDTH, 1L, background ); /* L. POHC 90/10/08 */
  210.   
  211.   set_maze_sizes(width, height);
  212.   XSelectInput(dpy, win,
  213.            ExposureMask | ButtonPressMask | StructureNotifyMask );
  214.   
  215.   gc = XCreateGC(dpy, win, 0L, 0); /* L. POHC 90/10/08 */
  216.   cgc = XCreateGC(dpy, win, 0L, 0); /* L. POHC 90/10/08 */
  217.   
  218.   gray = XCreateBitmapFromData (dpy, win, gray1_bits, 
  219.                 gray1_width, gray1_height);
  220.  
  221.   if (reverse)    {
  222.       XSetForeground(dpy, gc, WhitePixel(dpy, screen));
  223.       XSetBackground(dpy, gc, BlackPixel(dpy, screen));
  224.       XSetForeground(dpy, cgc, BlackPixel(dpy, screen)); 
  225.       XSetBackground(dpy, cgc, WhitePixel(dpy, screen)); 
  226.       XSetWindowBackground(dpy, win, BlackPixel(dpy, screen));
  227.   }
  228.   else {
  229.       XSetForeground(dpy, gc, BlackPixel(dpy, screen));
  230.       XSetBackground(dpy, gc, WhitePixel(dpy, screen));
  231.       XSetForeground(dpy, cgc, WhitePixel(dpy, screen)); 
  232.       XSetBackground(dpy, cgc, BlackPixel(dpy, screen)); 
  233.       XSetWindowBackground(dpy, win, WhitePixel(dpy, screen)); 
  234.   }
  235.   XSetStipple (dpy, cgc, gray);
  236.   XSetFillStyle (dpy, cgc, FillOpaqueStippled);
  237.   
  238.   if  (!(logo_map = XCreateBitmapFromData(dpy, win, logo_bits,
  239.                       logo_width, logo_height))) {
  240.     fprintf(stderr, "Can't create logo pixmap\n");
  241.     exit (1);
  242.   }
  243.   size_hints.flags =  flags | PMinSize ;
  244.   size_hints.x = x;
  245.   size_hints.y = y;
  246.   size_hints.width = width;
  247.   size_hints.height = height;
  248.   size_hints.min_width = MIN_W;
  249.   size_hints.min_height = MIN_H;
  250.   
  251.   XSetStandardProperties(dpy, win, "Xmaze", "Xmaze", logo_map,
  252.              argv, argc, &size_hints);
  253.   XMapWindow(dpy, win);
  254.   srandom(getpid());
  255.  
  256.   while (1) {                            /* primary execution loop [ rhess ] */
  257.     if (check_events()) continue ;
  258.     if (restart || stop) goto pop;
  259.     switch (state) {
  260.     case 1:
  261.       initialize_maze();
  262.       break;
  263.     case 2:
  264.       XClearWindow(dpy, win);
  265.       draw_maze_border();
  266.       break;
  267.     case 3:
  268.       create_maze();
  269.       break;
  270.     case 4:
  271.       XFlush(dpy);
  272.       if (pause) /* POHC 90/10/30 */
  273.          sleep(2);
  274.       break;
  275.     case 5:
  276.       solve_maze();
  277.       break;
  278.     default:
  279.       XFlush(dpy) ;
  280.       if (pause) /* POHC 90/10/30 */
  281.          sleep(4);
  282.       state = 0 ;
  283.       break;
  284.     }
  285.     state = ++state ;
  286.   pop:
  287.     if (restart) {
  288.       restart = 0 ;
  289.       stop = 0 ;
  290.       state = 1 ;
  291.       XGetWindowAttributes(dpy, win, &win_attr);
  292.       width = win_attr.width ;
  293.       height = win_attr.height ;
  294.       set_maze_sizes(width, height);
  295.       XClearWindow(dpy, win);
  296.       XFlush(dpy) ;
  297.     }
  298.   }
  299. }
  300.  
  301.  
  302. check_events()                                  /* X event handler [ rhess ] */
  303. {
  304.   XEvent    e;
  305.  
  306.   if (XPending(dpy)) {
  307.     XNextEvent(dpy, &e);
  308.     switch (e.type) {
  309.     case ButtonPress:
  310.       switch (e.xbutton.button) {
  311.       case 3:
  312.     XFreeGC(dpy, gc);
  313.     XFreeGC(dpy, cgc);
  314.     XDestroyWindow(dpy, win);
  315.     XCloseDisplay(dpy);
  316.     exit(0);
  317.     break;
  318.       case 2:
  319.     stop = !stop ;
  320.     if (state == 5) state = 4 ;
  321.     else {
  322.       restart = 1;
  323.       stop = 0;
  324.     }
  325.     break;
  326.       default:
  327.     restart = 1 ;
  328.     stop = 0 ;
  329.     break;
  330.       }
  331.       break;
  332.     case ConfigureNotify:
  333.       restart = 1;
  334.       break;
  335.     case UnmapNotify:
  336.       stop = 1;
  337.       XClearWindow(dpy, win);
  338.       XFlush(dpy);
  339.       break;
  340.     case Expose:
  341.       restart = 1;
  342.       break;
  343.     }
  344.     return(1);
  345.   }
  346.   return(0);
  347. }      
  348.  
  349.  
  350. usage(cmd)
  351.      char    *cmd;
  352. {
  353.   fprintf(stderr, "usage: %s -S -p -r [-g geometry] [-d display]\n", cmd);
  354. }
  355.  
  356.  
  357. set_maze_sizes(width, height)
  358. {
  359. #ifdef MSDOS /* POHC 90/10/08 */
  360.   maze_size_x = ((width / SQ_SIZE_X) > MAX_MAZE_SIZE_X )?MAX_MAZE_SIZE_X:(width / SQ_SIZE_X);
  361.   maze_size_y = ((height / SQ_SIZE_Y) > MAX_MAZE_SIZE_Y )?MAX_MAZE_SIZE_Y:(height / SQ_SIZE_Y);
  362. #else /* !MSDOS */
  363.   maze_size_x = width / SQ_SIZE_X;
  364.   maze_size_y = height / SQ_SIZE_Y;
  365. #endif /* !MSDOS */
  366.   
  367. }
  368.  
  369.  
  370. initialize_maze()         /* draw the surrounding wall and start/end squares */
  371. {
  372.   register int i, j, wall;
  373.   
  374.   /* initialize all squares */
  375.   for ( i=0; i<maze_size_x; i++) {
  376.     for ( j=0; j<maze_size_y; j++) {
  377.       maze[i][j] = 0;
  378.     }
  379.   }
  380.   
  381.   /* top wall */
  382.   for ( i=0; i<maze_size_x; i++ ) {
  383.     maze[i][0] |= WALL_TOP;
  384.   }
  385.   
  386.   /* right wall */
  387.   for ( j=0; j<maze_size_y; j++ ) {
  388.     maze[maze_size_x-1][j] |= WALL_RIGHT;
  389.   }
  390.   
  391.   /* bottom wall */
  392.   for ( i=0; i<maze_size_x; i++ ) {
  393.     maze[i][maze_size_y-1] |= WALL_BOTTOM;
  394.   }
  395.   
  396.   /* left wall */
  397.   for ( j=0; j<maze_size_y; j++ ) {
  398.     maze[0][j] |= WALL_LEFT;
  399.   }
  400.   
  401.   /* set start square */
  402.   wall = get_random(4);
  403.   switch (wall) {
  404.   case 0:    
  405.     i = get_random(maze_size_x);
  406.     j = 0;
  407.     break;
  408.   case 1:    
  409.     i = maze_size_x - 1;
  410.     j = get_random(maze_size_y);
  411.     break;
  412.   case 2:    
  413.     i = get_random(maze_size_x);
  414.     j = maze_size_y - 1;
  415.     break;
  416.   case 3:    
  417.     i = 0;
  418.     j = get_random(maze_size_y);
  419.     break;
  420.   }
  421.   maze[i][j] |= START_SQUARE;
  422.   maze[i][j] |= ( DOOR_IN_TOP >> wall );
  423.   maze[i][j] &= ~( WALL_TOP >> wall );
  424.   cur_sq_x = i;
  425.   cur_sq_y = j;
  426.   start_x = i;
  427.   start_y = j;
  428.   start_dir = wall;
  429.   sqnum = 0;
  430.   
  431.   /* set end square */
  432.   wall = (wall + 2)%4;
  433.   switch (wall) {
  434.   case 0:
  435.     i = get_random(maze_size_x);
  436.     j = 0;
  437.     break;
  438.   case 1:
  439.     i = maze_size_x - 1;
  440.     j = get_random(maze_size_y);
  441.     break;
  442.   case 2:
  443.     i = get_random(maze_size_x);
  444.     j = maze_size_y - 1;
  445.     break;
  446.   case 3:
  447.     i = 0;
  448.     j = get_random(maze_size_y);
  449.     break;
  450.   }
  451.   maze[i][j] |= END_SQUARE;
  452.   maze[i][j] |= ( DOOR_OUT_TOP >> wall );
  453.   maze[i][j] &= ~( WALL_TOP >> wall );
  454.   end_x = i;
  455.   end_y = j;
  456.   end_dir = wall;
  457.   
  458.   /* set logo */
  459.   if ( (maze_size_x > 15) && (maze_size_y > 15) ) {
  460.     logo_x = get_random(maze_size_x - LOGOSIZE - 6) + 3;
  461.     logo_y = get_random(maze_size_y - LOGOSIZE - 6) + 3;
  462.     
  463.     for (i=0; i<LOGOSIZE; i++) {
  464.       for (j=0; j<LOGOSIZE; j++) {
  465.     maze[logo_x + i][logo_y + j] |= DOOR_IN_TOP;
  466.       }
  467.     }
  468.   }
  469.   else
  470.     logo_y = logo_x = -1;
  471. }
  472.  
  473.  
  474. create_maze()             /* create a maze layout given the intiialized maze */
  475. {
  476.   register int i, newdoor;
  477.   
  478.   do {
  479.     move_list[sqnum].x = cur_sq_x;
  480.     move_list[sqnum].y = cur_sq_y;
  481.     move_list[sqnum].dir = newdoor;
  482.     while ( ( newdoor = choose_door() ) == -1 ) { /* pick a door */
  483.       if ( backup() == -1 ) { /* no more doors ... backup */
  484.     return; /* done ... return */
  485.       }
  486.     }
  487.     
  488.     /* mark the out door */
  489.     maze[cur_sq_x][cur_sq_y] |= ( DOOR_OUT_TOP >> newdoor );
  490.     
  491.     switch (newdoor) {
  492.     case 0: cur_sq_y--;
  493.       break;
  494.     case 1: cur_sq_x++;
  495.       break;
  496.     case 2: cur_sq_y++;
  497.       break;
  498.     case 3: cur_sq_x--;
  499.       break;
  500.     }
  501.     sqnum++;
  502.     
  503.     /* mark the in door */
  504.     maze[cur_sq_x][cur_sq_y] |= ( DOOR_IN_TOP >> ((newdoor+2)%4) );
  505.     
  506.     /* if end square set path length and save path */
  507.     if ( maze[cur_sq_x][cur_sq_y] & END_SQUARE ) {
  508.       path_length = sqnum;
  509.       for ( i=0; i<path_length; i++) {
  510.     save_path[i].x = move_list[i].x;
  511.     save_path[i].y = move_list[i].y;
  512.     save_path[i].dir = move_list[i].dir;
  513.       }
  514.     }
  515.     
  516.   } while (1);
  517.   
  518. }
  519.  
  520.  
  521. choose_door()                                            /* pick a new path */
  522. {
  523.   int candidates[3];
  524.   register int num_candidates;
  525.   
  526.   num_candidates = 0;
  527.   
  528.  topwall:
  529.   /* top wall */
  530.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_TOP )
  531.     goto rightwall;
  532.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_TOP )
  533.     goto rightwall;
  534.   if ( maze[cur_sq_x][cur_sq_y] & WALL_TOP )
  535.     goto rightwall;
  536.   if ( maze[cur_sq_x][cur_sq_y - 1] & DOOR_IN_ANY ) {
  537.     maze[cur_sq_x][cur_sq_y] |= WALL_TOP;
  538.     maze[cur_sq_x][cur_sq_y - 1] |= WALL_BOTTOM;
  539.     draw_wall(cur_sq_x, cur_sq_y, 0);
  540.     goto rightwall;
  541.   }
  542.   candidates[num_candidates++] = 0;
  543.   
  544.  rightwall:
  545.   /* right wall */
  546.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_RIGHT )
  547.     goto bottomwall;
  548.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_RIGHT )
  549.     goto bottomwall;
  550.   if ( maze[cur_sq_x][cur_sq_y] & WALL_RIGHT )
  551.     goto bottomwall;
  552.   if ( maze[cur_sq_x + 1][cur_sq_y] & DOOR_IN_ANY ) {
  553.     maze[cur_sq_x][cur_sq_y] |= WALL_RIGHT;
  554.     maze[cur_sq_x + 1][cur_sq_y] |= WALL_LEFT;
  555.     draw_wall(cur_sq_x, cur_sq_y, 1);
  556.     goto bottomwall;
  557.   }
  558.   candidates[num_candidates++] = 1;
  559.   
  560.  bottomwall:
  561.   /* bottom wall */
  562.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_BOTTOM )
  563.     goto leftwall;
  564.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_BOTTOM )
  565.     goto leftwall;
  566.   if ( maze[cur_sq_x][cur_sq_y] & WALL_BOTTOM )
  567.     goto leftwall;
  568.   if ( maze[cur_sq_x][cur_sq_y + 1] & DOOR_IN_ANY ) {
  569.     maze[cur_sq_x][cur_sq_y] |= WALL_BOTTOM;
  570.     maze[cur_sq_x][cur_sq_y + 1] |= WALL_TOP;
  571.     draw_wall(cur_sq_x, cur_sq_y, 2);
  572.     goto leftwall;
  573.   }
  574.   candidates[num_candidates++] = 2;
  575.   
  576.  leftwall:
  577.   /* left wall */
  578.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_IN_LEFT )
  579.     goto donewall;
  580.   if ( maze[cur_sq_x][cur_sq_y] & DOOR_OUT_LEFT )
  581.     goto donewall;
  582.   if ( maze[cur_sq_x][cur_sq_y] & WALL_LEFT )
  583.     goto donewall;
  584.   if ( maze[cur_sq_x - 1][cur_sq_y] & DOOR_IN_ANY ) {
  585.     maze[cur_sq_x][cur_sq_y] |= WALL_LEFT;
  586.     maze[cur_sq_x - 1][cur_sq_y] |= WALL_RIGHT;
  587.     draw_wall(cur_sq_x, cur_sq_y, 3);
  588.     goto donewall;
  589.   }
  590.   candidates[num_candidates++] = 3;
  591.   
  592.  donewall:
  593.   if (num_candidates == 0)
  594.     return ( -1 );
  595.   if (num_candidates == 1)
  596.     return ( candidates[0] );
  597.   return ( candidates[ get_random(num_candidates) ] );
  598.   
  599. }
  600.  
  601.  
  602. backup()                                                  /* back up a move */
  603. {
  604.  sqnum--;
  605. #ifdef InstantC
  606.   if (sqnum < 0) return(0); /* RATIONAL */
  607. #endif
  608.   cur_sq_x = move_list[sqnum].x;
  609.   cur_sq_y = move_list[sqnum].y;
  610.   return ( sqnum );
  611. }
  612.  
  613.  
  614. draw_maze_border()                                  /* draw the maze outline */
  615. {
  616.   register int i, j;
  617.   
  618.   
  619.   for ( i=0; i<maze_size_x; i++) {
  620.     if ( maze[i][0] & WALL_TOP ) {
  621.       XDrawLine(dpy, win, gc,
  622.         border_x + SQ_SIZE_X * i,
  623.         border_y,
  624.         border_x + SQ_SIZE_X * (i+1),
  625.         border_y);
  626.     }
  627.     if ((maze[i][maze_size_y - 1] & WALL_BOTTOM)) {
  628.       XDrawLine(dpy, win, gc,
  629.         border_x + SQ_SIZE_X * i,
  630.         border_y + SQ_SIZE_Y * (maze_size_y),
  631.         border_x + SQ_SIZE_X * (i+1),
  632.         border_y + SQ_SIZE_Y * (maze_size_y));
  633.     }
  634.   }
  635.   for ( j=0; j<maze_size_y; j++) {
  636.     if ( maze[maze_size_x - 1][j] & WALL_RIGHT ) {
  637.       XDrawLine(dpy, win, gc,
  638.         border_x + SQ_SIZE_X * maze_size_x,
  639.         border_y + SQ_SIZE_Y * j,
  640.         border_x + SQ_SIZE_X * maze_size_x,
  641.         border_y + SQ_SIZE_Y * (j+1));
  642.     }
  643.     if ( maze[0][j] & WALL_LEFT ) {
  644.       XDrawLine(dpy, win, gc,
  645.         border_x,
  646.         border_y + SQ_SIZE_Y * j,
  647.         border_x,
  648.         border_y + SQ_SIZE_Y * (j+1));
  649.     }
  650.   }
  651.   
  652.   if (logo_x != -1) {
  653.     XCopyPlane(dpy, logo_map, win, gc,
  654.            0, 0, logo_width, logo_height,
  655.            border_x + 3 + SQ_SIZE_X * logo_x,
  656.            border_y + 3 + SQ_SIZE_Y * logo_y, 1L); /* L. POHC 90/10/08 */
  657.   }
  658.   
  659.   draw_solid_square( start_x, start_y, start_dir, gc);
  660.   draw_solid_square( end_x, end_y, end_dir, gc);
  661. }
  662.  
  663.  
  664. draw_wall(i, j, dir)                                   /* draw a single wall */
  665.      int i, j, dir;
  666. {
  667.   switch (dir) {
  668.   case 0:
  669.     XDrawLine(dpy, win, gc,
  670.           border_x + SQ_SIZE_X * i, 
  671.           border_y + SQ_SIZE_Y * j,
  672.           border_x + SQ_SIZE_X * (i+1), 
  673.           border_y + SQ_SIZE_Y * j);
  674.     break;
  675.   case 1:
  676.     XDrawLine(dpy, win, gc,
  677.           border_x + SQ_SIZE_X * (i+1), 
  678.           border_y + SQ_SIZE_Y * j,
  679.           border_x + SQ_SIZE_X * (i+1), 
  680.           border_y + SQ_SIZE_Y * (j+1));
  681.     break;
  682.   case 2:
  683.     XDrawLine(dpy, win, gc,
  684.           border_x + SQ_SIZE_X * i, 
  685.           border_y + SQ_SIZE_Y * (j+1),
  686.           border_x + SQ_SIZE_X * (i+1), 
  687.           border_y + SQ_SIZE_Y * (j+1));
  688.     break;
  689.   case 3:
  690.     XDrawLine(dpy, win, gc,
  691.           border_x + SQ_SIZE_X * i, 
  692.           border_y + SQ_SIZE_Y * j,
  693.           border_x + SQ_SIZE_X * i, 
  694.           border_y + SQ_SIZE_Y * (j+1));
  695.     break;
  696.   }
  697. }
  698.  
  699.  
  700. draw_solid_square(i, j, dir, gc)          /* draw a solid square in a square */
  701.      register int i, j, dir;
  702.      GC    gc;
  703. {
  704.   switch (dir) {
  705.   case 0: XFillRectangle(dpy, win, gc,
  706.              border_x + 3 + SQ_SIZE_X * i, 
  707.              border_y - 3 + SQ_SIZE_Y * j, 
  708.              SQ_SIZE_X - 6, SQ_SIZE_Y);
  709.     break;
  710.   case 1: XFillRectangle(dpy, win, gc,
  711.              border_x + 3 + SQ_SIZE_X * i, 
  712.              border_y + 3 + SQ_SIZE_Y * j, 
  713.              SQ_SIZE_X, SQ_SIZE_Y - 6);
  714.     break;
  715.   case 2: XFillRectangle(dpy, win, gc,
  716.              border_x + 3 + SQ_SIZE_X * i, 
  717.              border_y + 3 + SQ_SIZE_Y * j, 
  718.              SQ_SIZE_X - 6, SQ_SIZE_Y);
  719.     break;
  720.   case 3: XFillRectangle(dpy, win, gc,
  721.              border_x - 3 + SQ_SIZE_X * i, 
  722.              border_y + 3 + SQ_SIZE_Y * j, 
  723.              SQ_SIZE_X, SQ_SIZE_Y - 6);
  724.     break;
  725.   }
  726.   XFlush(dpy);
  727. #ifdef    notdef
  728.   (void) check_events();
  729. #endif
  730. }
  731.  
  732.  
  733. solve_maze()                             /* solve it with graphical feedback */
  734. {
  735.   int i;
  736.   
  737.   
  738.   /* plug up the surrounding wall */
  739.   maze[start_x][start_y] |= (WALL_TOP >> start_dir);
  740.   maze[end_x][end_y] |= (WALL_TOP >> end_dir);
  741.   
  742.   /* initialize search path */
  743.   i = 0;
  744.   path[i].x = end_x;
  745.   path[i].y = end_y;
  746.   path[i].dir = -1;
  747.   
  748.   /* do it */
  749.   while (1) {
  750.     if ( ++path[i].dir >= 4 ) {
  751.       i--;
  752.       draw_solid_square( (int)(path[i].x), (int)(path[i].y), 
  753.             (int)(path[i].dir), cgc);
  754.     }
  755.     else if ( ! (maze[path[i].x][path[i].y] & 
  756.          (WALL_TOP >> path[i].dir))  && 
  757.          ( (i == 0) || ( (path[i].dir != 
  758.                   (path[i-1].dir+2)%4) ) ) ) {
  759.       enter_square(i);
  760.       i++;
  761.       if ( maze[path[i].x][path[i].y] & START_SQUARE ) {
  762.     return;
  763.       }
  764.     } 
  765.     if (check_events()) return;
  766.     /* Abort solve on expose - cheapo repaint strategy */
  767.   }
  768.  
  769.  
  770. enter_square(n)                            /* move into a neighboring square */
  771.      int n;
  772. {
  773.   draw_solid_square( (int)path[n].x, (int)path[n].y, 
  774.             (int)path[n].dir, gc);
  775.   
  776.   path[n+1].dir = -1;
  777.   switch (path[n].dir) {
  778.   case 0: path[n+1].x = path[n].x;
  779.     path[n+1].y = path[n].y - 1;
  780.     break;
  781.   case 1: path[n+1].x = path[n].x + 1;
  782.     path[n+1].y = path[n].y;
  783.     break;
  784.   case 2: path[n+1].x = path[n].x;
  785.     path[n+1].y = path[n].y + 1;
  786.     break;
  787.   case 3: path[n+1].x = path[n].x - 1;
  788.     path[n+1].y = path[n].y;
  789.     break;
  790.   }
  791. }
  792.  
  793. /* ----<eof> */
  794.